using System;
using Microsoft.SPOT;

namespace Microsoft.Xna.Framework
{
    public struct Vector3
    {
        private static Vector3 zero = new Vector3(0);
        private static Vector3 one = new Vector3(1);
        private static Vector3 unitX = new Vector3(1, 0, 0);
        private static Vector3 unitY = new Vector3(0, 1, 0);
        private static Vector3 unitZ = new Vector3(0, 0, 1);

        public float X;
        public float Y;
        public float Z;

        public static Vector3 Zero
        {
            get { return zero; }
        }

        public static Vector3 One
        {
            get { return one; }
        }

        public static Vector3 UnitX
        {
            get { return unitX; }
        }

        public static Vector3 UnitY
        {
            get { return unitY; }
        }

        public static Vector3 UnitZ
        {
            get { return unitY; }
        }

        public Vector3(float value)
        {
            this.X = value;
            this.Y = value;
            this.Z = value;
        }

        public Vector3(float x, float y, float z)
        {
            this.X = x;
            this.Y = y;
            this.Z = z;
        }

        public Vector3(Vector2 vector, float z)
        {
            this.X = vector.X;
            this.Y = vector.Y;
            this.Z = z;
        }

        public override int GetHashCode()
        {
            return this.X.GetHashCode() + this.Y.GetHashCode() + this.Z.GetHashCode();
        }

        public static Vector3 Add(Vector3 value1, Vector3 value2)
        {
            return new Vector3(value1.X + value2.X, value1.Y + value2.Y, value1.Z + value2.Z);
        }

        public static Vector3 operator +(Vector3 value1, Vector3 value2)
        {
            return new Vector3(value1.X + value2.X, value1.Y + value2.Y, value1.Z + value2.Z);
        }

        public static Vector3 Subtract(Vector3 value1, Vector3 value2)
        {
            return new Vector3(value1.X - value2.X, value1.Y - value2.Y, value1.Z - value2.Z);
        }

        public static Vector3 operator -(Vector3 value1, Vector3 value2)
        {
            return new Vector3(value1.X - value2.X, value1.Y - value2.Y, value1.Z - value2.Z);
        }

        public static Vector3 operator -(Vector3 value)
        {
            return new Vector3(-value.X, -value.Y, -value.Z);
        }

        public static Vector3 operator *(Vector3 value1, Vector3 value2)
        {
            return new Vector3(value1.X * value2.X, value1.Y * value2.Y, value1.Z * value2.Z);
        }

        public static Vector3 operator *(Vector3 value1, float value2)
        {
            return new Vector3(value1.X * value2, value1.Y * value2, value1.Z * value2);
        }

        public static Vector3 operator /(Vector3 value1, float value2)
        {
            float divisor = 1 / value2;
            return new Vector3(value1.X * divisor, value1.Y * divisor, value1.Z * divisor);
        }

        public bool Equals(Vector3 value)
        {
            return value.X == this.X && value.Y == this.Y && this.Z == value.Z;
        }

        public override bool Equals(object obj)
        {
            if (obj is Vector3)
            {
                return Equals((Vector3)obj);
            }
            return false;
        }

        public static bool operator ==(Vector3 value1, Vector3 value2)
        {
            return (value1.X == value2.X) && (value1.Y == value2.Y) && (value1.Z == value2.Z);
        }

        public static bool operator !=(Vector3 value1, Vector3 value2)
        {
            return (value1.X != value2.X) || (value1.Y != value2.Y) || (value1.Z != value2.Z);
        }

        public override string ToString()
        {
            return string.Concat("{X:", X.ToString(), " Y:", Y.ToString(), " Z:", Z.ToString(), "}");
        }

        public float LengthSquared()
        {
            return X * X + Y * Y + Z * Z;
        }
    }
}
